package com.lewin.ringroad.service.impl;

import com.lewin.commons.constants.CommonResponseCode;
import com.lewin.commons.entity.LewinResult;
import com.lewin.ringroad.dao.CommonMapper;
import com.lewin.ringroad.entity.RadarDirectionPO;
import com.lewin.ringroad.entity.RadarStatisticsDataPO;
import com.lewin.ringroad.entity.RadarStatisticsDataVO;
import com.lewin.ringroad.net.handler.RaysunHandler;
import com.lewin.ringroad.service.IRadarService;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;

/**
 * @author Jun
 * @since 1.0.0
 */
@Service
public class RadarServiceImpl implements IRadarService {

    private final CommonMapper commonMapper;
    private final List<RadarDirectionPO> directionPOList;

    public RadarServiceImpl(CommonMapper commonMapper) {
        this.commonMapper = commonMapper;
        directionPOList = commonMapper.allRadarDirection();
    }

    @Override
    public LewinResult<List<RadarStatisticsDataVO>> statistics(String radarId) {
        var twinPO = RaysunHandler.dtIdAndDTMap.get(radarId);
        if (twinPO == null) {
            return LewinResult.fail(CommonResponseCode.DATA_NOT_EXIST);
        }
        final var bizId = twinPO.getBizId();

        // 获取前 48 个小时的数据
        var lst = timesGet();
        var results = commonMapper.listByTimes(bizId, lst)
                .stream()
                .map(RadarStatisticsDataPO::toVO)
                .sorted(Comparator.comparing(RadarStatisticsDataVO::getTimeAt))
                .toList();
        var result = lst.stream().map(t -> {
            return results.stream().filter(e -> e.getTimeAt().equals(t))
                    .findFirst()
                    .orElseGet(() -> new RadarStatisticsDataVO()
                            .setTraffic(0)
                            .setTimeAt(t)
                            .setOccupationRate(0d)
                            .setAverageSpeed(0d)
                            .setQueueLen(0d));
        }).toList();

        return LewinResult.ok(result);
    }

    @Override
    public LewinResult<List<RadarStatisticsDataVO>> line(String name) {
        // 中环东、西、北线
        if ("east".equalsIgnoreCase(name) ||
                "west".equalsIgnoreCase(name) ||
                "north".equalsIgnoreCase(name)) {
            // 获取前 48 个小时的数据
            var lst = timesGet();

            // 抓取设备
            // 这里的 radarId 是 bizId
            var radarIdList = directionPOList.stream()
                    .filter(t -> Objects.equals(name, t.getLoopLine()))
                    .map(RadarDirectionPO::getId)
                    .map(String::valueOf)
                    .toList();

            // 抓取设备数据
            var dataPOS = commonMapper.listByBizIdsAndTimes(radarIdList, lst);
            var results = new ArrayList<RadarStatisticsDataVO>();
            for (var timeAt : lst) {
                var list = dataPOS.stream().filter(t -> t.getTimeAt().equals(timeAt))
                        .toList();
                if (ObjectUtils.isEmpty(list)) {
                    var dataVO = new RadarStatisticsDataVO()
                            .setQueueLen(0d)
                            .setTraffic(0)
                            .setAverageSpeed(0d)
                            .setOccupationRate(0d)
                            .setTimeAt(timeAt);
                    results.add(dataVO);
                }else {
                    var dataVO = calculate(list, timeAt).toVO();
                    results.add(dataVO);
                }
            }
            results.sort(Comparator.comparing(RadarStatisticsDataVO::getTimeAt));

            return LewinResult.ok(results);
        }
        return LewinResult.fail(CommonResponseCode.ILLEGAL_ARGS);
    }

    private RadarStatisticsDataPO calculate(List<RadarStatisticsDataPO> lst, String timeAt) {
        int traffic = 0;
        double averageSpeed = 0d;
        double occupationRate = 0d;
        double queueLen = 0d;
        int count = 0;
        for (var dataPO : lst) {
            if (!dataPO.isValidData()) {
                continue;
            }
            count++;
            traffic += dataPO.getTraffic();
            averageSpeed += dataPO.getAverageSpeed();
            occupationRate += dataPO.getOccupationRate();
            queueLen += dataPO.getQueueLen();
        }
        if (count != 0) {
            traffic = traffic / count;
            averageSpeed = averageSpeed / count;
            occupationRate = occupationRate / count;
            queueLen = queueLen / count;
        }
        return new RadarStatisticsDataPO()
                .setTraffic(traffic)
                .setTimeAt(timeAt)
                .setAverageSpeed(averageSpeed)
                .setOccupationRate(occupationRate)
                .setQueueLen(queueLen);
    }

    private static List<String> timesGet() {
        var result = new ArrayList<String>();
        var now = LocalDateTime.now();
        var yesterday = now.minusDays(1);
        var yes = yesterday.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        for (int i = 0; i < 24; i++) {
            var n = String.valueOf(i);
            if (i < 10) {
                n = "0" + i;
            }
            result.add(yes + n);
        }

        var to = now.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        for (int i = 0; i < now.getHour(); i++) {
            var n = String.valueOf(i);
            if (i < 10) {
                n = "0" + i;
            }
            result.add(to + n);
        }

        return result;
    }
}
